package cgHttp

import (
	"bytes"
	"encoding/json"
	"io"
	"io/ioutil"
	"net/http"
	"time"

	"gitee.com/zzzcommon/common-go/cgUtils"
)

var default_timeout = 10 * time.Second

// * struct *
// Description: http操作返回对象
type HttpResponse struct {
	StatusCode int
	BodyString string
	BodyBytes  []byte
	Response   *http.Response
	Err        error
}

// * end *

// * struct *
// Description: HttpClient
type HttpClient struct {
	Timeout time.Duration
}

func (c *HttpClient) Get(url string) *HttpResponse {

	httpResponse := &HttpResponse{
		http.StatusInternalServerError,
		"",
		nil,
		nil,
		nil,
	}

	timeout := default_timeout
	if c.Timeout != 0 {
		timeout = c.Timeout
	}
	client := http.Client{
		Timeout: timeout,
	}
	resp, err := client.Get(url)
	if err != nil {
		httpResponse.Err = err
		return httpResponse
	}
	defer resp.Body.Close()
	html, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		httpResponse.Err = err
		return httpResponse
	}
	httpResponse.BodyString = string(html)
	httpResponse.BodyBytes = html
	httpResponse.StatusCode = resp.StatusCode
	httpResponse.Response = resp
	return httpResponse
}

type PostParams struct {
	Url         string
	Body        interface{}
	ContentType *string
	Headers     map[string]string
}

func (c *HttpClient) Post(postParams *PostParams) *HttpResponse {
	httpResponse := &HttpResponse{
		http.StatusInternalServerError,
		"",
		nil,
		nil,
		nil,
	}

	timeout := default_timeout
	if c.Timeout != 0 {
		timeout = c.Timeout
	}
	client := http.Client{
		Timeout: timeout,
	}
	client.CloseIdleConnections()

	if postParams.Body == nil {
		postParams.Body = struct{}{}
	}
	var jsonBytes []byte
	switch postParams.Body.(type) {
	case []byte:
		jsonBytes = postParams.Body.([]byte)
	default:
		var err error
		jsonBytes, err = json.Marshal(postParams.Body)
		if err != nil {
			httpResponse.Err = err
			return httpResponse
		}
	}

	req, err := http.NewRequest("POST", postParams.Url, bytes.NewReader(jsonBytes))

	if err != nil {
		httpResponse.Err = err
		return httpResponse
	}

	if postParams.ContentType == nil {
		postParams.ContentType = cgUtils.Ptr("application/json;charset=UTF-8")
	}

	req.Header.Set("Content-Type", *postParams.ContentType)
	for k, v := range postParams.Headers {
		req.Header.Set(k, v)
	}

	resp, err := client.Do(req)
	if err != nil {
		httpResponse.Err = err
		return httpResponse
	}
	defer resp.Body.Close()
	html, err := io.ReadAll(resp.Body)
	if err != nil {
		httpResponse.Err = err
		return httpResponse
	}
	httpResponse.BodyString = string(html)
	httpResponse.BodyBytes = html
	httpResponse.StatusCode = resp.StatusCode
	httpResponse.Response = resp
	return httpResponse
}

// * end *
